/*
 * Copyright 2012-2013 EZC Group S.A. RCS Luxembourg B140949
 * 
 * Licensed under the Apache License, Version 2.0 (the "License"); you may not
 * use this file except in compliance with the License. You may obtain a copy of
 * the License at
 * 
 * http://www.apache.org/licenses/LICENSE-2.0
 * 
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
 * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
 * License for the specific language governing permissions and limitations under
 * the License.
 */
package com.yobidrive.y3.v1;

import java.io.InputStream;
import java.io.OutputStream;
import java.util.List;

import com.yobidrive.y3.exceptions.Y3Exception;
import com.yobidrive.y3.v1.model.CreateFlowEventResult;
import com.yobidrive.y3.v1.model.CreateFlowResult;
import com.yobidrive.y3.v1.model.DeleteNodeResult;
import com.yobidrive.y3.v1.model.FinalizePairingResult;
import com.yobidrive.y3.v1.model.GetAttachedKeysListResult;
import com.yobidrive.y3.v1.model.GetBrandingResult;
import com.yobidrive.y3.v1.model.GetDriveDetailsResult;
import com.yobidrive.y3.v1.model.GetDriveListResult;
import com.yobidrive.y3.v1.model.GetEditionResult;
import com.yobidrive.y3.v1.model.GetExternalAccountPairingResult;
import com.yobidrive.y3.v1.model.GetFlowEventResult;
import com.yobidrive.y3.v1.model.GetFlowResult;
import com.yobidrive.y3.v1.model.GetFlowUpdateResult;
import com.yobidrive.y3.v1.model.GetFlowsConfigurationResult;
import com.yobidrive.y3.v1.model.GetFlowsListResult;
import com.yobidrive.y3.v1.model.GetItemLinkDetailsResult;
import com.yobidrive.y3.v1.model.GetNodeContentResult;
import com.yobidrive.y3.v1.model.GetNodeDetailsResult;
import com.yobidrive.y3.v1.model.GetPairingStatusResult;
import com.yobidrive.y3.v1.model.GetUserConfigurationResult;
import com.yobidrive.y3.v1.model.GetUserListResult;
import com.yobidrive.y3.v1.model.KeyValue;
import com.yobidrive.y3.v1.model.LeafContentMetadata;
import com.yobidrive.y3.v1.model.ManageMemberResult;
import com.yobidrive.y3.v1.model.RequestPairingResult;
import com.yobidrive.y3.v1.model.User;

/**
 * Version 1.0 of the Y3 interface.
 * 
 * Defines all methods that are supported by the current version of the backend.
 * 
 * @author David
 */

public interface Y3 {

	/**
	 * Log to the Y3-Backend. 
	 * 
	 * Login is done in a two-phases process:
	 * 	- Recovery of a challenge
	 * 	- Response to the challenge and generation of a unique token
	 * 
	 * This method encapsulates the whole process and returns the token if 
	 * everything went fine. 
	 * 
	 * @param userName
	 * @param password
	 * @return the Y3 token
	 * @throws Y3Exception
	 */
	String login(String userName, String password) throws Y3Exception;
	
	/**
	 * Attach the given token to the client. 
	 * Use it if you already know a token and don't want to login again.
	 * No check is done here, if token is invalid subsequent calls to the server
	 * will throw exceptions.
	 * 
	 * @param token
	 * @throws Y3Exception
	 */
	void attachToken(String userName, String token) throws Y3Exception;
	
	/**
	 * Token have a limited validity (5 minutes) and must be manually refreshed
	 * from time to time. Using an invalid token will result in authentication 
	 * error being throw by the server.
	 * 
	 * If the refresh token method ends in error, it means that the token is not
	 * valid anymore and thus a login() must be done again. In case of a new login
	 * every already opened eSafe drives will have to be reopened using the openSafe
	 * method.  
	 * 
	 * Refreshing is very similar to the login phase it uses the same two-phases process.
	 * Only difference is that during a refresh a token is initially present and will 
	 * have is validity period extended if everything is fine (on the other hand, the 
	 * login method will always return a new token, thus leading to automatic closing 
	 * of eSafe drives).  
	 * 
	 * @param userName
	 * @param password
	 * @return the refreshed token
	 * @throws Y3Exception
	 */
	String refreshToken(String userName, String password) throws Y3Exception;
	String refreshToken(String userName, String password, String token) throws Y3Exception;
	
	/**
	 * Basic token refresh methods that doesn't require the response to a challenge.
	 * Used only for the beta version of the web-site and will be replaced as soon as
	 * the unified login method will be implemented
	 * 
	 * @return
	 * @throws Y3Exception
	 */
	String refreshTokenBasic() throws Y3Exception;
	
	/**
	 * Open a safe using the user private key.
	 * A valid token must have previously been retrieved using the login() or 
	 * attachToken() methods, otherwise server will return an error. 
	 * 
	 * If opening succeed, recovered secret is directly attached (so no need to 
	 * call attachSecret after).
	 * 
	 * @param driveId
	 * @param userPrivateKey
	 * @throws Y3Exception
	 * @return the safe secret
	 */
	String openSafe(String driveId, String secretBase64) throws Y3Exception;
	
	/**
	 * Attach the given secret to the client.
	 * A valid safe secret must be attached prior to any calls on a eSafe drive otherwise 
	 * server will throw security errors.
	 * 
	 * @param secret
	 * @throws Y3Exception
	 */
	void attachSecret(String secret) throws Y3Exception;
	
	/**
	 * Get configuration info for the logged in user.
	 * It's a list of key value pair that can be empty.
	 * 
	 * 
	 * 
	 * @return
	 * @throws Y3Exception
	 */
	GetUserConfigurationResult getUserConfiguration(boolean withMembershipUsage) throws Y3Exception;
	
	/**
	 * Get configuration info for the logged in user.
	 * It's a list of key value pair that can be empty.
	 * 
	 * 
	 * 
	 * @return
	 * @throws Y3Exception
	 */
	// GetUserConfigurationResult getUserConfiguration(boolean withMembershipUsage, boolean renewS3Key) throws Y3Exception;
	
	/*
	 * External accounts (OpenID/OAtuh) completion 
	 */
	
	/**
	 * Check the current pairing status for an external account pairing.
	 * Pairing must be done (i.e. link with an email address) before being able to login with an external account.
	 *  
	 * @param uuid
	 * @return
	 * @throws Y3Exception
	 */
	GetExternalAccountPairingResult getExternalAccountPairing(String uuid) throws Y3Exception;
	
	/**
	 * Update the current pairing status for an external account pairing.
	 * 
	 * @param uuid
	 * @param email
	 * @param firstName
	 * @param lastName
	 * @param validationCode
	 * @return
	 * @throws Y3Exception
	 */
	void setExternalAccountPairing(String uuid, String email, String firstName, String lastName, String language) throws Y3Exception;
	
	/**
	 * Complete the email verification of the account and returns an Y3 Token if everything was ok.
	 * @param uuid
	 * @param validationCode
	 * @throws Y3Exception
	 */
	String completeExternalAccountPairing(String uuid, String validationCode) throws Y3Exception;
	
	
	
	
	/*
	 * Pairing and keys functions 
	 */
	/**
	 * Request a soft pairing for the given list of drives.
	 * A label can be added for user-friendliness
	 * 
	 * @param List of drive ids to pair with.
	 * @return id of the pairing request
	 * @throws Y3Exception
	 */
	RequestPairingResult requestDriveOpening(List<String> driveList, String pairingLabel) throws Y3Exception;
	
	/**
	 * Request a soft pairing eKey attachment.
	 * @param pairingLabel
	 * @return
	 * @throws Y3Exception
	 */
	RequestPairingResult requestAttach(String pairingLabel) throws Y3Exception;
	
	/**
	 * Request a soft pairing backup key attachment
	 * 
	 * @param pairingLabel
	 * @return
	 * @throws Y3Exception
	 */
	RequestPairingResult requestBackupAttach(String pairingLabel) throws Y3Exception;
	
	/**
	 * Request a soft eKey attachment, directly providing the default "rescue" private key.
	 * @param pairingLabel
	 * @param rescuePEM
	 * @return
	 * @throws Y3Exception
	 */
	RequestPairingResult requestAttach(String pairingLabel, String rescuePEM) throws Y3Exception;
	
	/**
	 * Request a strong authentication procedure
	 * @return
	 * @throws Y3Exception
	 */
	RequestPairingResult requestStrongAuthentication() throws Y3Exception;
	
	/**
	 * Finalize a pairing process. If something goes wrong an exception is thrown.
	 * Result contains the list of driveId / secrets in case of an opening request, serial of new key n case of
	 * an attachment.
	 * 
	 * @param pairingId id of the soft pairing 
	 * @param pairingPin pin of the soft pairing
	 * @throws Y3Exception 
	 */
	FinalizePairingResult finalizePairing(String pairingId, String pairingPin) throws Y3Exception;
	
	/**
	 * Finalize a key pairing process.
	 * 
	 * @param userEmail
	 * @param pairingPin
	 * @param secretAESB64
	 * @param keyName
	 * @return
	 * @throws Y3Exception
	 */
	FinalizePairingResult finalizeAttachPairing(String pairingPin, String secretAESB64, String keyName, String controlCode) throws Y3Exception;
	
	/**
	 * Get the current status of a pairing request.
	 * Security code is optional (if it was given when requesting the pairing it must be send, if there was none it's not needed)
	 * 
	 * @param pairingId
	 * @return
	 * @throws Y3Exception
	 */
	GetPairingStatusResult getPairingStatus(String pairingId, String securityCode) throws Y3Exception;
	
	/**
	 * Return the list of electronic keys attached to the user account.
	 * @throws Y3Exception
	 */
	GetAttachedKeysListResult getAttachedKeysList() throws Y3Exception;
	
	
	
	/*
	 * User account creation
	 */
	
	/**
	 * Create a new user account. Given email will have to be validated before using the account.  
	 *   
	 * @param email will be the identifier of the new account
	 * @param firstName first name of the user [optional]
	 * @param lastName  last name of the user [optional]
	 * @param passwordSha SHA1 hash of the user desired password
	 * @throws Y3Exception
	 */
	void createUserAccount(String email, String firstName, String lastName, String passwordSha, String preferedLanguage) throws Y3Exception;
	
	/**
	 * Special account creation mode if comming from a linkUid (no need to validate email address as link are unique per email)
	 * 
	 * @param email
	 * @param firstName
	 * @param lastName
	 * @param passwordSha
	 * @param preferedLanguage
	 * @throws Y3Exception
	 */
	void createUserAccount(String linkUniversalId, String email, String firstName, String lastName, String passwordSha, String preferedLanguage) throws Y3Exception;
	
	/**
	 * Update preferences of current user.
	 * Leave password empty if not changed
	 * 
	 * @param email
	 * @param firstName
	 * @param lastName
	 * @param passwordSha
	 * @param preferedLanguage
	 * @throws Y3Exception
	 */
	void updateUserAccount(String firstName, String lastName, String passwordSha, String preferedLanguage,
						   String company, String vatnumber, String address, String zip, String city, String country,
						   String vatType, String rcsNumber) throws Y3Exception;
	
	/**
	 * Validate a user account using the validation code that is sent to the account email address.
	 */
	void validateUserAccount(String email, String validationCode) throws Y3Exception;
	
	/**
	 * Request the reset of the password of the given account.
	 * 
	 * @param email
	 * @throws Y3Exception
	 */
	void resetPassword(String email) throws Y3Exception;
	
	/**
	 * Complete the password reset for the given id.
	 * 
	 * @param uniqueId
	 * @param newPasswordSha
	 * @throws Y3Exception
	 */
	void resetPassword(String uniqueId, String newPasswordSha) throws Y3Exception;
	
	/**
	 * Unblock the user account
	 * @param uniqueId
	 * @throws Y3Exception
	 */
	void unblockAccount(String email, String uniqueId) throws Y3Exception;
	
	/**
	 * Resend the account validation email. 
	 * @param email
	 * @throws Y3Exception
	 */
	void resentValidationEmail(String email, boolean isExternalAccount) throws Y3Exception;
	
	
	/**
	 * Recover the list of drives for the user.
	 * The client must be logged-in or exception will be thrown.
	 * 
	 * @return array of drives id
	 * @throws Y3Exception
	 */
	GetDriveListResult getDriveList() throws Y3Exception;
	
	/**
	 * Create a new drive.
	 * 
	 * @param driveId
	 * @param friendlyName
	 * @return
	 * @throws Y3Exception
	 */
	void createDrive(String driveId, String friendlyName, String preferedLanguage, String mailPolicy, String publishPolicy, boolean highConfidentiality) throws Y3Exception;
	
	/**
	 * Update drive settings
	 * @param driveId
	 * @param friendlyName
	 * @param preferedLanguage
	 * @throws Y3Exception
	 */
	void updateDrive(String driveId, String friendlyName, String preferedLanguage, String mailPolicy, String publishPolicy, String downloadPolicy ) throws Y3Exception;
	
	/**
	 * Delete a drive.
	 * Drive must be empty to be deleted.
	 * User home drive cannot be deleted. 
	 * 
	 * @param driveId
	 * @throws Y3Exception
	 */
	void deleteDrive(String driveId) throws Y3Exception;
	
	/**
	 * Translate an uid into a path.
	 * 
	 * @param driveId
	 * @param uid
	 * @return
	 * @throws Y3Exception
	 */
	String getPathFromUid(String driveId, String uid) throws Y3Exception;
	
	/**
	 * Recover the details of the drive (list of owners, programmed keys, ...)
	 * User must be an owner of the drive to be able to access this information.
	 * 
	 * @param driveId
	 * @return
	 * @throws Y3Exception
	 */
	GetDriveDetailsResult getDriveDetails(String driveId) throws Y3Exception;
	
	/**
	 * List the content of a given node on a drive
	 * @param driveId unique of the drive.
	 * @param path path of the node inside the drive
	 * @return the list of item names inside the path of the drive
	 * @throws Y3Exception
	 */
	GetNodeContentResult getNodeContent(String driveId, String nodePath) throws Y3Exception;
	GetNodeContentResult getNodeContent(String driveId, String nodePath, String nameFrom, int limit, String order) throws Y3Exception;
	
	/**
	 * List the content of a given node on a drive
	 * @param driveId unique of the drive.
	 * @param nodeUid uid of the node on the drive
	 * @return the list of item names inside the path of the drive
	 * @throws Y3Exception
	 */
	GetNodeContentResult getNodeContentByUid(String driveId, String nodeUid) throws Y3Exception;
	GetNodeContentResult getNodeContentByUid(String driveId, String nodeUid, String nameFrom, int limit, String order) throws Y3Exception;
	
	/**
	 * Recover the details of a given node (or leaf)
	 */
	GetNodeDetailsResult getNodeDetails(String drive,String nodePath) throws Y3Exception;
	GetNodeDetailsResult getNodeDetailsByUid(String drive,String nodeUid) throws Y3Exception;
	
	/**
	 * Create a node with path nodePath on drive id.
	 * @param drive 
	 * @param nodePath
	 * @throws Y3Exception if creation is not possible (already exist, no rights, ...)
	 */
	void createNode(String drive, String nodePath) throws Y3Exception;
	
	/**
	 * Recover the content (blob) of a leaf and send it into the destination OutputStream
	 * @param driveId
	 * @param leafPath
	 * @return the metadata of the content that was written into destination stream
	 * @throws Y3Exception
	 */
	LeafContentMetadata getLeafContent(OutputStream destination, String driveId, String leafPath) throws Y3Exception;
	LeafContentMetadata getLeafContent(OutputStream destination, String driveId, String leafPath, String version) throws Y3Exception;
	LeafContentMetadata getLeafContentByUid(OutputStream destination, String driveId, String leafUid) throws Y3Exception;
	LeafContentMetadata getLeafContentByUid(OutputStream destination, String driveId, String leafUid, String version) throws Y3Exception;
	
	/**
	 * Recover the metadata about the given leaf but doesn't download anything
	 * @param driveId
	 * @param leafPath
	 * @return
	 * @throws Y3Exception
	 */
	LeafContentMetadata getLeafContentMetadata(String driveId, String leafPath) throws Y3Exception;
	LeafContentMetadata getLeafContentMetadata(String driveId, String leafPath, String version) throws Y3Exception;
	LeafContentMetadata getLeafContentMetadataByUid(String driveId, String leafUid) throws Y3Exception;
	LeafContentMetadata getLeafContentMetadataByUid(String driveId, String leafUid, String version) throws Y3Exception;
	
	/**
	 * Recover a unique download link id for the given leaf content.
	 * Link is valid for only a few minute and must be used directly after being recovered.
	 * 
	 * @param driveId
	 * @param leafUid
	 * @param version
	 * @return
	 * @throws Y3Exception
	 */
	String getDownloadLinkForUid(String driveId, String leafUid, String version) throws Y3Exception;
	
	/**
	 * Send the content of the input stream into the given leaf.
	 * If the leaf doesn't exist it will created.
	 * 
	 * To avoid unnecessary transfers, calling assertCanSetLeafContent() before this method is highly
	 * encouraged.
	 * 
	 * @param source inputStream to be sent
	 * @param metadata metadata about the stream (length, contentType);
	 * @param driveId destination drive
	 * @param leafPath destination leaf path
	 * @param action action to play at end of upload (optional)
	 * @throws Y3Exception
	 */
	void setLeafContent(InputStream source, LeafContentMetadata metadata, String driveId, String leafPath, String action, String actionParam) throws Y3Exception;

	/**
	 * Send the content of the input stream into the given leaf
	 * The leaf must exists or an error will be thrown 
	 */
	void setLeafContentByUid(InputStream source, LeafContentMetadata metadata, String driveId, String leafUid, String action, String actionParam) throws Y3Exception;
	
	/**
	 * Ensure that it's possible to set the content of the given leaf.
	 * An exception will be thrown if it's not possible (missing rights, unauthenticated, ...)
	 * 
	 * When using the HttpClient implementation, it's very useful to test that it's possible to do the 
	 * set before actually doing it to avoid sending useless data on the line.
	 * 
	 * The traditional way of handling this problem would be to use the HTTP Header Expect-continue.
	 * Problem is that the current implementation of the server doesn't handle the Expect-continue requests
	 * correctly (Tomcat directly sends a 100-Continue response without even calling the servlet).
	 * 
	 * @param driveId
	 * @param leafPath
	 * @return
	 * @throws Y3Exception
	 */
	void assertCanSetLeafContent(String driveId, String leafPath, long size) throws Y3Exception; 
	void assertCanSetLeafContentByUid(String driveId, String leafUid, long size) throws Y3Exception; 
	
	/*
	 * Node and leaf management methods (renaming, deleting, managing rights, ...) 
	 */
	/**
	 * Change the name of a node (or leaf).
	 * Throws exceptions in case node is not found or name is invalid. 
	 * 
	 * @param driveId
	 * @param nodePath
	 * @param newName
	 * @throws Y3Exception
	 */
	void renameNode(String driveId, String nodePath, String newName) throws Y3Exception;
	void renameNodeByUId(String driveId, String nodeUid, String newName) throws Y3Exception;
	
	/**
	 * Publish the content of the leaf.
	 * Optionally send a message to the readers.
	 * 
	 * @param driveId
	 * @param nodePath
	 * @param message
	 * @throws Y3Exception
	 */
	void publishLeaf(String driveId, String nodePath, String message) throws Y3Exception;
	void publishLeafByUid(String driveId, String nodeUid, String message) throws Y3Exception;
	
	/**
	 * Delete a node (or leaf).
	 * Deletion is not cancellable.
	 * 
	 * @param driveId
	 * @param nodePath
	 * @throws Y3Exception
	 */
	DeleteNodeResult deleteNode(String driveId, String nodePath) throws Y3Exception;
	DeleteNodeResult deleteNodeByUid(String driveId, String nodeUid) throws Y3Exception;
	
	/**
	 * Add readers and writers to the given node / leaf
	 */
	ManageMemberResult addReaders(String driveId, String nodePath, String[] newReaders, String message) throws Y3Exception;
	ManageMemberResult addWriters(String driveId, String nodePath, String[] newWriters, String message) throws Y3Exception;
	ManageMemberResult addReadersByUId(String driveId, String nodeUid, String[] newReaders, String message) throws Y3Exception;
	ManageMemberResult addWritersByUId(String driveId, String nodeUid, String[] newWriters, String message) throws Y3Exception;

	/**
	 * Remove readers and writers from the given node / leaf
	 */
	ManageMemberResult removeReaders(String driveId, String nodePath, String[] readersToRemove) throws Y3Exception;
	ManageMemberResult removeWriters(String driveId, String nodePath, String[] writersToRemove) throws Y3Exception;
	ManageMemberResult removeReadersByUId(String driveId, String nodeUid, String[] readersToRemove) throws Y3Exception;
	ManageMemberResult removeWritersByUId(String driveId, String nodeUid, String[] writersToRemove) throws Y3Exception;
	
	/**
	 * Add and remove drive owners, aka managers.
	 * Requires user to be owner. 
	 */
	ManageMemberResult addOwners(String driveId, String[] newOwners) throws Y3Exception;
	ManageMemberResult removeOwners(String driveId, String[] ownersToRemove) throws Y3Exception;
	
	/**
	 * Program and revoke user keys on a given drive
	 * Requires user to be owner.
	 */
	ManageMemberResult programUserKey(String driveId, String[] usersToProgram) throws Y3Exception;
	ManageMemberResult revokeUserKey(String driveId, String[] usersToRevoke) throws Y3Exception;
	
	/**
	 * Activate safe mode on given drive
	 * Requires user to be owner.
	 */
	void activateSafe(String driveId) throws Y3Exception;
	
	/*
	 * Payments management
	 */
	
	/**
	 * Ask for a one-time payment url for the current connected user.
	 * @return
	 * @throws Y3Exception
	 */
	String paymentRequest() throws Y3Exception;
	
	/**
	 * Use the voucher for the current connected user
	 * @param voucherCode
	 * @throws Y3Exception
	 */
	void useVoucher(String voucherCode, boolean isTrial) throws Y3Exception;
	
	/*
	 * Quick sharing
	 */
	void finalizeQuickSharing(String driveId, String sharingPath, String timestamp, String recipients, String message) throws Y3Exception;
	
	/*
	 * Branding methods
	 */
	
	/**
	 * Set the logo 
	 * 
	 * @param file
	 * @param type
	 * @throws Y3Exception
	 */
	void setBrandingLogo(InputStream stream, LeafContentMetadata metadata, String type) throws Y3Exception;
	void delBrandingLogo(String type) throws Y3Exception;
	void setBrandingColor(KeyValue[] values) throws Y3Exception;
	
	/**
	 * Recover branding info for a given drive
	 * @param drive
	 * @throws Y3Exception
	 */
	GetBrandingResult getBranding(String drive) throws Y3Exception;
	
	/*
	 * Item link details recovery methods
	 */
	GetItemLinkDetailsResult getItemLinkDetails(String linkId, String email) throws Y3Exception;
	LeafContentMetadata getItemLinkContent(OutputStream destination, String linkId, String email) throws Y3Exception;
	
	/*
	 * Users management methods, only available to users registered as admins.
	 * If no password is given one will be generated.
	 */
	GetUserListResult getUserList() throws Y3Exception;
	GetUserListResult getUserList(String emailFrom, int limit) throws Y3Exception;
	void addUser(String email, String firstName, String lastName, String passwordSha, String role) throws Y3Exception;
	void updUser(String email, String firstName, String lastName, String role) throws Y3Exception;
	void delUser(String email) throws Y3Exception;
	
	/*
	 * Enterprise mode methods
	 */
	GetEditionResult getEdition() throws Y3Exception;
	
	/*
	 * Utility methods
	 */
	/**
	 * Set the address from which call are originating used in cases where the API is used by 
	 * a middleware app, i.e.web application
	 * 
	 *  EndUser --> WebApplication -- y3api --> YobidriveServer
	 *   IP A             IP B                      IP C
	 *   
	 * By default the YobidriveServer will see all calls coming from IP B, but in some cases it 
	 * could be interesting to also know the originating address.   
	 *  
	 * @param addr
	 */
	void setOriginatingAddr(String addr);
	
	/**
	 * For "unconnected" calls tracking (optional) 
	 * @param uuid
	 */
	void setUserUUID(String uuid);
	
	/**
	 * Temporary method to allow easy migration of old keys to the new safe manager system
	 * available since 20.Sept.2012
	 *  
	 * @param PEM
	 * @throws Y3Exception
	 */
	void migratePEMKey(String PEM) throws Y3Exception;
	
	
	/*
	 * FLows related methods
	 */
	
	/**
	 * Creates a new flow. Base name is used to compute the aliases.
	 * @return
	 * @throws Y3Exception
	 */
	CreateFlowResult createFlow(String baseName, String activationCode) throws Y3Exception;
	
	/**
	 * Creates a new flow event. Name and message are optional.
	 * @param name
	 * @param message
	 * @return
	 * @throws Y3Exception
	 */
	CreateFlowEventResult createFlowEvent(String flowAlias, String flowKey, String name, String message) throws Y3Exception;
	
	/**
	 * Finalize a flow event 
	 * @param eventCid
	 * @throws Y3Exception
	 */
	void finalizeFlowEvent(String flowAlias, String flowKey, String eventCid) throws Y3Exception;
	
	/**
	 * Recover the flow details given its alias
	 * @param alias
	 * @return
	 * @throws Y3Exception
	 */
	GetFlowResult getFlow(String flowAlias, String flowKey) throws Y3Exception;
	
	/**
	 * Returns the details of a flow event given a flow id and an event cid
	 * @param flowAlias
	 * @param eventCid
	 * @return
	 * @throws Y3Exception
	 */
	GetFlowEventResult getFlowEvent(String flowAlias, String flowKey, String eventCid) throws Y3Exception;
	
	/**
	 * Returns info about updates that occurred since systemTs
	 * @param flowAlias
	 * @param systemTs
	 * @return
	 * @throws Y3Exception
	 */
	GetFlowUpdateResult getFlowUpdates(String flowAlias, String flowKey,  String systemTs) throws Y3Exception;
	
	/**
	 * Returns the public configuration of the Flows! server as a list of KeyValue pair.
	 * @return
	 * @throws Y3Exception
	 */
	GetFlowsConfigurationResult getFlowsConfiguration() throws Y3Exception;
	
	/**
	 * Delete a flow event
	 * @param flowAlias
	 * @param flowKey
	 * @param eventCid
	 * @return
	 * @throws Y3Exception
	 */
	void deleteFlowEvent(String flowAlias, String flowKey, String eventCid) throws Y3Exception;
	
	/**
	 * Flow admin action, requires a valid token and administrator rights or exception will be thrown
	 */
	GetFlowsListResult getFlowsList(String nameFrom, int limit) throws Y3Exception;
	
	/**
	 * Send a raw admin command and recover raw result.
	 * Requires a valid token and administrator rights or exception will be thrown
	 * @param command
	 * @return
	 * @throws Y3Exception
	 */
	String playAdminCommand(String command) throws Y3Exception;
}
